package z_mxsTest.testCleanCommonWithList;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 多语言代码注释清理工具
 * 
 * 功能说明：
 * 1. 批量清理目录下所有支持类型文件中的//单行注释和/* * /多行注释
 * 2. 支持的文件类型：Java(.java)、C(.c)、C++(.cpp/.cxx)、C#(.cs)、JavaScript(.js)等
 * 3. 操作安全：清理前需用户确认，仅修改含注释的文件，保留原文件格式
 * 
 * 使用方法：
 * 1. 运行程序后，点击"浏览目录"选择需要处理的根目录
 * 2. 点击"开始清理注释"，在弹出的确认框中确认操作（建议先备份文件）
 * 3. 通过日志区域查看处理进度和结果，可点击"清空日志"重新开始
 * 
 * 目录结构解析：
 * - 程序会递归处理所选根目录及其所有子目录
 * - 仅处理SUPPORTED_EXTENSIONS数组中定义的文件类型
 * - 忽略不支持的文件类型，不做任何修改
 */
public class testCleanCommonWithList extends JFrame {
    private static final long serialVersionUID = 1L;

    // 支持的文件后缀（可根据需要扩展）
    private static final String[] SUPPORTED_EXTENSIONS = {
        ".java", ".c", ".cpp", ".cxx", ".cc", 
        ".cs", ".js", ".ts", ".php", ".m"
    };

    // 注释匹配正则表达式（先匹配多行注释，再匹配单行注释）
    private static final Pattern COMMENT_PATTERN = Pattern.compile(
        "/\\*[\\s\\S]*?\\*/|//.*", 
        Pattern.CASE_INSENSITIVE
    );

    // GUI组件
    private JTextField dirPathField;
    private JTextArea logArea;
    private File selectedDir;

    public testCleanCommonWithList() {
        initUI();
    }

    /**
     * 初始化图形用户界面
     */
    private void initUI() {
        // 窗口基础设置
        setTitle("多语言代码注释清理工具");
        setSize(850, 650);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);
        setLayout(new BorderLayout(15, 15));

        // 设置内容面板边框
        Container contentPane = getContentPane();
        if (contentPane instanceof JComponent) {
            ((JComponent) contentPane).setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
        }

        // 顶部：目录选择区域
        JPanel topPanel = new JPanel(new BorderLayout(10, 10));
        JLabel dirLabel = new JLabel("选择目标根目录（将递归处理所有子目录）：");
        dirLabel.setFont(new Font("微软雅黑", Font.PLAIN, 12));
        
        dirPathField = new JTextField();
        dirPathField.setEditable(false);
        dirPathField.setFont(new Font("Consolas", Font.PLAIN, 12));
        
        JButton browseDirBtn = new JButton("浏览目录");
        browseDirBtn.setFont(new Font("微软雅黑", Font.PLAIN, 12));
        browseDirBtn.addActionListener(new BrowseDirActionListener());

        topPanel.add(dirLabel, BorderLayout.WEST);
        topPanel.add(dirPathField, BorderLayout.CENTER);
        topPanel.add(browseDirBtn, BorderLayout.EAST);
        add(topPanel, BorderLayout.NORTH);

        // 中间：日志显示区域
        JPanel logPanel = new JPanel(new BorderLayout(10, 10));
        JLabel logLabel = new JLabel("处理日志（实时显示进度）：");
        logLabel.setFont(new Font("微软雅黑", Font.PLAIN, 12));
        
        logArea = new JTextArea();
        logArea.setEditable(false);
        logArea.setFont(new Font("Consolas", Font.PLAIN, 11));
        logArea.setLineWrap(true);
        logArea.setWrapStyleWord(true);
        
        JScrollPane logScroll = new JScrollPane(logArea);
        logScroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);

        logPanel.add(logLabel, BorderLayout.NORTH);
        logPanel.add(logScroll, BorderLayout.CENTER);
        add(logPanel, BorderLayout.CENTER);

        // 底部：操作按钮区域
        JPanel btnPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 30, 15));
        JButton startCleanBtn = new JButton("开始清理注释");
        startCleanBtn.setFont(new Font("微软雅黑", Font.PLAIN, 12));
        startCleanBtn.addActionListener(new StartCleanActionListener());
        
        JButton clearLogBtn = new JButton("清空日志");
        clearLogBtn.setFont(new Font("微软雅黑", Font.PLAIN, 12));
        clearLogBtn.addActionListener(new ClearLogActionListener());

        btnPanel.add(startCleanBtn);
        btnPanel.add(clearLogBtn);
        add(btnPanel, BorderLayout.SOUTH);
    }

    /**
     * 目录选择按钮事件监听器
     */
    private class BrowseDirActionListener implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            JFileChooser dirChooser = new JFileChooser();
            dirChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
            dirChooser.setDialogTitle("选择需要清理注释的根目录");
            dirChooser.setCurrentDirectory(new File(System.getProperty("user.dir")));

            int selectResult = dirChooser.showOpenDialog(testCleanCommonWithList.this);
            if (selectResult == JFileChooser.APPROVE_OPTION) {
                selectedDir = dirChooser.getSelectedFile();
                dirPathField.setText(selectedDir.getAbsolutePath());
                log("已选择根目录：" + selectedDir.getAbsolutePath());
            }
        }
    }

    /**
     * 开始清理按钮事件监听器
     */
    private class StartCleanActionListener implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            if (selectedDir == null || !selectedDir.exists()) {
                JOptionPane.showMessageDialog(
                    testCleanCommonWithList.this,
                    "请先选择有效的根目录！",
                    "操作错误",
                    JOptionPane.ERROR_MESSAGE
                );
                return;
            }

            int confirmResult = JOptionPane.showConfirmDialog(
                testCleanCommonWithList.this,
                "确认开始清理吗？\n1. 工具将递归处理所选目录下所有支持类型文件\n" +
                "2. 操作会直接覆盖原文件，请确保已备份重要代码！",
                "重要确认",
                JOptionPane.YES_NO_OPTION,
                JOptionPane.WARNING_MESSAGE
            );

            if (confirmResult == JOptionPane.YES_OPTION) {
                new Thread(new CleanTask()).start();
            } else {
                log("用户取消了清理操作");
            }
        }
    }

    /**
     * 清空日志按钮事件监听器
     */
    private class ClearLogActionListener implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            logArea.setText("");
            log("日志已清空");
        }
    }

    /**
     * 清理任务线程
     */
    private class CleanTask implements Runnable {
        @Override
        public void run() {
            log("=== 注释清理任务开始 ===");
            int totalFileCount = 0;
            int cleanedFileCount = 0;
            int skippedFileCount = 0;

            try {
                totalFileCount = countSupportedFiles(selectedDir);
                log("在根目录下共发现 " + totalFileCount + " 个支持类型的文件");

                cleanedFileCount = cleanSupportedFiles(selectedDir);
                skippedFileCount = totalFileCount - cleanedFileCount;

                log("=== 注释清理任务完成 ===");
                log("成功清理：" + cleanedFileCount + " 个文件（含注释并已移除）");
                log("跳过文件：" + skippedFileCount + " 个文件（无注释或无需处理）");
            } catch (Exception ex) {
                log("=== 注释清理任务异常终止 ===");
                log("异常原因：" + ex.getMessage());
                ex.printStackTrace();
            }
        }
    }

    /**
     * 统计支持类型的文件总数
     */
    private int countSupportedFiles(File dir) {
        int count = 0;
        File[] fileArray = dir.listFiles();

        if (fileArray == null) {
            log("警告：目录 [" + dir.getAbsolutePath() + "] 无法访问，已跳过");
            return 0;
        }

        for (File file : fileArray) {
            if (file.isDirectory()) {
                count += countSupportedFiles(file);
            } else if (isSupportedFile(file)) {
                count++;
            }
        }
        return count;
    }

    /**
     * 清理所有支持类型的文件
     */
    private int cleanSupportedFiles(File dir) throws IOException {
        int cleanedCount = 0;
        File[] fileArray = dir.listFiles();

        if (fileArray == null) {
            log("警告：目录 [" + dir.getAbsolutePath() + "] 无法访问，已跳过");
            return 0;
        }

        for (File file : fileArray) {
            if (file.isDirectory()) {
                cleanedCount += cleanSupportedFiles(file);
            } else if (isSupportedFile(file)) {
                boolean isCleaned = cleanCommentInFile(file);
                if (isCleaned) {
                    cleanedCount++;
                    log("✅ 清理成功：" + file.getAbsolutePath());
                } else {
                    log("ℹ️ 跳过文件：" + file.getAbsolutePath() + "（无注释可清理）");
                }
            }
        }
        return cleanedCount;
    }

    /**
     * 清理单个文件中的注释
     */
    private boolean cleanCommentInFile(File file) throws IOException {
        // 读取文件内容
        StringBuilder originalContent = new StringBuilder();
        try (BufferedReader br = new BufferedReader(
                new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8))) {
            String line;
            while ((line = br.readLine()) != null) {
                originalContent.append(line).append(System.lineSeparator());
            }
        }

        // 移除注释
        Matcher matcher = COMMENT_PATTERN.matcher(originalContent.toString());
        String cleanedContent = matcher.replaceAll("");

        // 内容无变化则不写入
        if (cleanedContent.equals(originalContent.toString())) {
            return false;
        }

        // 写入清理后的内容
        try (BufferedWriter bw = new BufferedWriter(
                new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8))) {
            bw.write(cleanedContent);
        }

        return true;
    }

    /**
     * 判断文件是否为支持的类型
     */
    private boolean isSupportedFile(File file) {
        String fileName = file.getName().toLowerCase();
        for (String ext : SUPPORTED_EXTENSIONS) {
            if (fileName.endsWith(ext)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 线程安全的日志记录方法
     */
    private void log(String message) {
        SwingUtilities.invokeLater(() -> {
            logArea.append(message + System.lineSeparator());
            logArea.setCaretPosition(logArea.getDocument().getLength());
        });
    }

    /**
     * 主方法：程序入口
     */
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            testCleanCommonWithList tool = new testCleanCommonWithList();
            tool.setVisible(true);
        });
    }
}
